package com.blindBox.front.handler.paperHandler.paperHandlerImpl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.blindBox.front.commonResult.MsgBackToFront;
import com.blindBox.front.dao_pojo.Paper;
import com.blindBox.front.dao_pojo.Paperchosebywho;
import com.blindBox.front.dao_pojo.User;
import com.blindBox.front.file.FileManager;
import com.blindBox.front.handler.paperHandler.AbstractPaperHandler;
import com.blindBox.front.parse.PaperParse;
import com.blindBox.front.parse.PathParse;
import com.blindBox.front.service.PaperService;
import com.blindBox.front.service.PaperchosebywhoService;
import com.blindBox.front.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

//纸条处理器
@Component("paperHandler")
public class PaperHandler implements AbstractPaperHandler {
    @Autowired
    private PaperService paperService;
    @Autowired
    private UserService userService;
    @Autowired
    private FileManager fileManager;
    @Autowired
    private PaperchosebywhoService paperchosebywhoService;
    @Value("${user.max_take_num}")
    private Integer max_take_num;
    @Value("${user.max_lauch_num}")
    private Integer max_lauch_num;
    @Value("${user.lauch_grant_num}")
    private Integer lauch_grant_num;
    @Autowired
    private PaperParse paperParse;
    //纸条的放入
    //纸条放入盲盒中后，用户投掷盲盒的数量加一
    @Override
    public synchronized MsgBackToFront paperPutIn(Paper paper)
    {
        //首先判断当前用户纸条投掷数量是否达到最大限制次数
           if(isOverMaxLaunchNum(paper.getUserid()))
           {
               return new MsgBackToFront(null,MsgBackToFront.OVER_MAX_LAUCH_NUMS);
           }
        //保存纸条到数据库
        //当前时间
        LocalDateTime now=LocalDateTime.now();
        paper.setUpDateTime(now);
        //加密自我介绍
        String encipher = paperParse.encipher(paper.getSelfinfo());
        paper.setSelfinfo(encipher);

        if(paperService.save(paper))
        {
            //这边后期需要加事务回滚
            //如果成功，再将对应用户的投掷盲盒数量加一
            boolean ret = userService.add_user_lauch_num(paper.getUserid());
           //给当用户增加奖励次数
            grantUserTakeNum(paper.getUserid(),this.lauch_grant_num);
            //数据库操作出现异常
            if(!ret)
                return new MsgBackToFront(null,MsgBackToFront.DATABASE_ERROR);
            //处理成功
            return new MsgBackToFront(null,MsgBackToFront.HANDLE_SUCCESS);
        }
            //数据库操作出现异常
            return new MsgBackToFront(null,MsgBackToFront.DATABASE_ERROR);
    }

    //用户每次投放一个纸条，就奖励用户抽取次数
    public void grantUserTakeNum(Integer u_id,Integer grantNum)
    {
        userService.up_user_take_num(u_id,grantNum);
    }


    public MsgBackToFront handleSelfImgs(MultipartFile[] imgs,Integer u_id)
    {
        //首先判断当前用户纸条投掷数量是否达到最大限制次数
        if(isOverMaxLaunchNum(u_id))
        {
            return new MsgBackToFront(null,MsgBackToFront.OVER_MAX_LAUCH_NUMS);
        }
        return fileManager.handleSelfImgs(imgs);
    }

    public MsgBackToFront handleSelfImgs(MultipartFile img)
    {
        return fileManager.handleSelfImgs(img);
    }

    //纸条的拿出，需要男还是女，以及当前用户的id
    @Override//1男 0女
    public synchronized MsgBackToFront paperTakeOut(Integer sex,Integer u_id)
    {
        //先判断当前用户当日拿出纸条数量是否超过最大的次数限制
        if(isOverMaxTakeOutNums(u_id))
        {
            return new MsgBackToFront(null,MsgBackToFront.OVER_MAX_TAKE_NUMS);
        }

        Paper paper = getPaperOneRandom(sex,u_id);
        if(paper==null)
        {
            //没有纸条可以抽取
            return new MsgBackToFront(null,MsgBackToFront.NONE_PAPER);
        }
        //将对应用户的拿取纸条的次数加一
        boolean ret = userService.add_user_take_num(u_id);
        if(!ret)
            return new MsgBackToFront(null,MsgBackToFront.DATABASE_ERROR);
        //都成功了，将要返回给前端展示的纸条，自我介绍进行解密
        String parse = paperParse.parse(paper.getSelfinfo());
        paper.setSelfinfo(parse);
        //返回抽到的纸条
        return new MsgBackToFront(paper,MsgBackToFront.HANDLE_SUCCESS);
    }

    @Override
    public MsgBackToFront delPaper(Integer p_id)
    {
        //先删除指定的文件,如果删除失败
        if(!delPaperImgs(p_id))
        {
            return new MsgBackToFront(null,MsgBackToFront.EXCEPTION_ERROR);
        }
        //删除成功，再删除数据库记录
        if(paperService.removeById(p_id)&&paperchosebywhoService.remove(new QueryWrapper<Paperchosebywho>().eq("p_id",p_id)))
            return new MsgBackToFront(null,MsgBackToFront.DATABASE_ERROR);
        return new MsgBackToFront(null,MsgBackToFront.HANDLE_SUCCESS);
    }

    //删除纸条里面传入的照片
   private  boolean delPaperImgs(Integer p_id)
   {
       Paper paper = paperService.getById(p_id);
       //判断用户是否上传了paper
       if(paper.getSelfImgs().equals("none")||paper.getSelfImgs().equals("")||paper.getSelfImgs()==null)
       {
           return true;
       }
       //上传了，进行删除操作
       File file=new File(fileManager.getImgsPrefix()+paper.getSelfImgs());

       System.out.println("======================================");
       System.out.println("删除照片的路径为: "+fileManager.getImgsPrefix()+paper.getSelfImgs());
       System.out.println("======================================");

       if(file.exists())
       {
           return file.delete();
       }
       return true;
   }

    //sex决定，从男性中抽取，还是女性中抽取
    //查询出所有纸条的id集合，然后在其中随机选择一个，返回
    public synchronized Paper getPaperOneRandom(Integer sex,Integer u_id)
    {
        //按照性别,查询出没有被抽取过的纸条---不能抽到自己
        List<Integer> paperIdsByList = paperService.getPaperIdsByList(sex,u_id);
        //纸条被抽完了，那么就重置所有纸条为未被抽取的状态
        if(paperIdsByList.size()==0)
        {
         paperService.emptyAllPaperStatus(sex);
            //再次查询
            paperIdsByList = paperService.getPaperIdsByList(sex,u_id);
        }
        //无纸条可供抽取
        if(paperIdsByList.size()==0)return null;
        //生成随机数
        Integer index = createRandomNum(paperIdsByList.size());
        //处理映射表
        Integer last_random_num = handleMappedTable(paperIdsByList, index, u_id);
       //暂时没有纸条可以进行抽取
        if(last_random_num==-1)
        {
            return null;
        }
        //伪删除纸条---当前纸条已经被抽取过了
        delPaperFake(paperIdsByList,index);
        //拿着抽取出来的幸运儿，去数据库中查出来，并返回
        return paperService.getById(paperIdsByList.get(last_random_num));
    }


    //生成随机数，随机抽取纸条
    public synchronized Integer createRandomNum(Integer size)
    {
        //随机抽取
        long  t = System.currentTimeMillis(); //获得当前时间的毫秒数
        Random random=new Random(t); //作为种子数传入到Random的构造器中
        //生成随机整数，范围不超过paperIdsByList.size()
        int index = random.nextInt(size);
         return index;
    }

    //将抽取到的纸条伪删除
    public synchronized void delPaperFake(List<Integer> paperIdsByList,Integer index)
    {
        //将被抽取到的纸条删除
        Paper paper=new Paper();
        paper.setId(paperIdsByList.get(index));
        paper.setDel(1);
        //先更新对应的纸条的del状态为1
        paperService.updateById(paper);
    }

    //映射表处理
    public synchronized Integer handleMappedTable(List<Integer> paperIdsByList,Integer index,Integer u_id)
    {
        Integer last_random_num=index;
        //往映射表中插入一条记录
        //如果当前映射表中，用户已经抽到了这个纸条，那么就不进行插入操作了
        //就再次进行五次随机抽取，直到五次结束，如果还是没有抽到了不一样的纸条，就不插入直接返回
        Paperchosebywho paperchosebywho=new Paperchosebywho();
        paperchosebywho.setP_id(paperIdsByList.get(index));
        paperchosebywho.setChose_user_id(u_id);
        //记录是否被当前用户重复抽取
        boolean repeat_chose=false;
        //数据库检查映射表中是否存在记录
        Paperchosebywho pcb = paperchosebywhoService.getOne(new QueryWrapper<Paperchosebywho>().eq("p_id", paperchosebywho.getP_id()).
                eq("chose_user_id", u_id));
        //纸条已经被当前用户抽取过了
        if(pcb!=null)
        {
            //再次循环随机10次抽取
            for(int i=0;i<20;i++)
            {
                last_random_num = createRandomNum(paperIdsByList.size());
                paperchosebywho.setP_id(paperIdsByList.get(last_random_num));
                Paperchosebywho ran_pcb_temp = paperchosebywhoService.getOne(new
                        QueryWrapper<Paperchosebywho>().eq("p_id", paperchosebywho.getP_id()).
                        eq("chose_user_id", u_id));
                //发现一个纸条当前用户没有抽取到过
                if(ran_pcb_temp==null)
                {
                    repeat_chose=true;
                    break;
                }
            }
        }
        else
        {
            //发现一个纸条当前用户没有抽取到过
            repeat_chose=true;
        }
        //是否存在纸条用户可以抽取
        if(repeat_chose)
        {
            //保存抽到的时间
            paperchosebywho.setChose_date(LocalDateTime.now());
            //保存到映射表中
            paperchosebywhoService.save(paperchosebywho);
            //如果第一次随机抽到了重复的，那么就返回最后随机五次其一的结果
            //返回最后一次使用到的随机数
            return last_random_num;
        }
        //暂时没有剩余纸条可供抽取，防止用户抽取到重复纸条
        return -1;
    }

    //先判断当前用户当日拿出纸条数量是否超过最大的次数限制
    public boolean isOverMaxTakeOutNums(Integer u_id)
    {
        User user = userService.getById(u_id);
        if(user.getTakeNum()>=max_take_num)
        {
            return true;
        }
        return false;
    }

    //判断当日用户投放纸条数量是否达到最大的次数限制
    public boolean isOverMaxLaunchNum(Integer u_id)
    {
        User user = userService.getById(u_id);
        if(user==null)return false;
        if(user.getLauchNum()>=max_lauch_num)
        {
            return true;
        }
        return false;
    }

    //获取当前用户拥有所有纸条
    public synchronized MsgBackToFront getUserAllPapers(Integer u_id)
    {
        List<Paper> allPapers = paperService.getUserAllPapers(u_id);
        if(allPapers==null||allPapers.size()==0)
        {
            //没有纸条
            return new MsgBackToFront(null,MsgBackToFront.NONE_PAPER);
        }
        //对纸条的内容进行解密
        for (Paper paper : allPapers) {
            paper.setSelfinfo(paperParse.parse(paper.getSelfinfo()));
        }
        //返回当前用户拥有的所有纸条
        return new MsgBackToFront(allPapers,MsgBackToFront.HANDLE_SUCCESS);
    }

     //返回当前用户抽取到的所有纸条
    public synchronized MsgBackToFront getUsersGetPapers(Integer u_id)
    {
        List<Map<Object, Object>> userGetPapers = paperchosebywhoService.getUserGetPapers(u_id);
        if(userGetPapers==null||userGetPapers.size()==0)
        {
            //没有纸条
            return new MsgBackToFront(null,MsgBackToFront.NONE_PAPER);
        }
        //纸条内容解密--为了照顾没有被加密过的纸条
        try
        {
            List<Map<Object, Object>> afterParse=new ArrayList<>();
            for (Map<Object, Object> paper : userGetPapers)
            {
                String selfInfo = (String)paper.get("selfInfo");
                String parse = paperParse.parse(selfInfo);
                paper.put("selfInfo",parse);
                afterParse.add(paper);
            }
            return new MsgBackToFront(afterParse,MsgBackToFront.HANDLE_SUCCESS);
        }
        catch (Exception e)
        {
            System.out.println("???????????");
            System.out.println("纸条解密失败");
            System.out.println("???????????");
        }
        //返回当前用户抽取到的所有纸条
        return new MsgBackToFront(null,MsgBackToFront.EXCEPTION_ERROR);
    }

    //返回当前用户发布并被别人抽取到的纸条
    public synchronized MsgBackToFront getUserPostAndChoseByOtherPaper(Integer u_id)
    {
        List<Map<Object, Object>> userPostAndChoseByOtherPaper = paperchosebywhoService.getUserPostAndChoseByOtherPaper(u_id);
        if(userPostAndChoseByOtherPaper==null||userPostAndChoseByOtherPaper.size()==0)
            return new MsgBackToFront(null,MsgBackToFront.NONE_PAPER);
        //纸条内容解密--为了照顾没有被加密过的纸条
        try
        {
            List<Map<Object, Object>> afterParse=new ArrayList<>();
            for (Map<Object, Object> paper : userPostAndChoseByOtherPaper)
            {
                String selfInfo = (String)paper.get("selfInfo");
                String parse = paperParse.parse(selfInfo);
                paper.put("selfInfo",parse);
                afterParse.add(paper);
            }
            return new MsgBackToFront(afterParse,MsgBackToFront.HANDLE_SUCCESS);
        }
        catch (Exception e)
        {
            System.out.println("???????????");
            System.out.println("纸条解密失败");
            System.out.println("???????????");
        }
        return new MsgBackToFront(null,MsgBackToFront.EXCEPTION_ERROR);
    }

}
